package cn.bonoon.kernel.support;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;

import cn.bonoon.entities.plugins.CodeGenerateEntity;
import cn.bonoon.kernel.annotations.CodeType;
import cn.bonoon.kernel.util.MD5Util;

/**
 * 编码生成器
 * @author jackson
 *
 */
public final class CodeGenerator {

	public final static int NUDEFINED = 0;
	public final static int MAX_LENGTH = 20;
	public final static int DEFAULT_LENGTH = 13;
	private final static Object LOCK = new Object();
	private final EntityManager entityManager;
	private final String key;
	private final CodeType type;
	private final int len;
	private String prefix = "";
	private Calendar calendar;
	private final static char digits[] = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9'};
	private final static String QL = "from CodeGenerateEntity x where x.key=? and x.prefix=?";
	
	public CodeGenerator(EntityManager entityManager, CodeType type, Class<?> cls, int len){
		this(entityManager, type, MD5Util.getMD5(cls.getName()), len);
	}
	
	public CodeGenerator(EntityManager entityManager, CodeType type, String key, int len){
		this.entityManager = entityManager;
		this.key = key;
		this.type = type;
		this.len = len > MAX_LENGTH || len < 1 ? DEFAULT_LENGTH : len;
		this.calendar = Calendar.getInstance();
	}
	
	public CodeGenerator(EntityManager entityManager, CodeType type, Class<?> cls){
		this(entityManager, type, cls, DEFAULT_LENGTH);
	}
	public CodeGenerator(EntityManager entityManager, Class<?> cls){
		this(entityManager, CodeType.MONTH, cls, DEFAULT_LENGTH);
	}
	public CodeGenerator(EntityManager entityManager, Class<?> cls, int len){
		this(entityManager, CodeType.MONTH, cls, len);
	}
	public String generate(){
		synchronized (LOCK) {
			//先尝试取出当前的记录
			StringBuilder prefix = new StringBuilder(this.prefix);
			switch (type) {
			case DAY:
				int d = calendar.get(Calendar.DAY_OF_MONTH);
				prefix.append(digits[d / 10]).append(digits[d % 10]);
			case MONTH:
				int m = calendar.get(Calendar.MONTH) + 1;
				prefix.append(digits[m / 10]).append(digits[m % 10]);
			case YEAR://日期格式为日月年
				prefix.append(calendar.get(Calendar.YEAR));
			}
			int len = this.len - prefix.length();
			for(int i = 0; i < len; i++) prefix.append(digits[0]);
			String pre = prefix.toString();
			List<CodeGenerateEntity> ls = entityManager.createQuery(QL, CodeGenerateEntity.class)
					.setParameter(1, key).setParameter(2, pre).getResultList();
			CodeGenerateEntity cge;
			int count = 1;
			if(ls.isEmpty()){
				cge = new CodeGenerateEntity();
				cge.setCount(count);
				cge.setKey(key);
				cge.setPrefix(pre);
				entityManager.persist(cge);
			}else{
				cge = ls.get(0);
				count += cge.getCount();
				cge.setCount(count);
				entityManager.merge(cge);
			}
			entityManager.flush();
			char csc[] = Integer.toString(count).toCharArray();
			if(csc.length > len) {
				//编码不够用
				throw new RuntimeException("编码不够用！");
			}
			char chs[] = pre.toCharArray();
			for(int i = chs.length - 1, j = csc.length - 1; j >= 0; j--, i--){
				chs[i] = csc[j];
			}
			return new String(chs);
		}
	}
	
	public CodeGenerator setNow(Date now) {
		calendar.setTime(now);
		return this;
	}
	
	public CodeGenerator setPrefix(String prefix) {
		this.prefix = prefix;
		return this;
	}
	
//	public static void main(String[]args){
//		StringBuilder str = new StringBuilder("444_");
//		char chs[] = {'3', '5'};
//		str.append(chs[0]).append(chs[1]);
////		str += chs[0] + chs[1];
//		System.out.println(chs[0]);
//		System.out.println(chs[1]);
//		System.out.println(str);
//		
//		int i = 54;
//		int q = (i * 52429) >>> (16+3);
//		int r = i - ((q << 3) + (q << 1));
////		Integer.toString(15);
////		Character.toChars(15);
////		char chs[] = new char[2];
////		chs[0] = 15/10;
////		chs[1] = 15%10;
//		System.out.println(digits[q]);
//		System.out.println(digits[r]);
//	}
}
